#include "EditorEditableTextView.h"
#include "EditorEditableTextViewModel.h"

#include "Widgets/TextWidget.h"
#include "Widgets/RectangleWidget.h"
#include "Widgets/Keyboard/KeyboardWidget.h"
#include "Widgets/Mouse/MouseWidget.h"
#include "Widgets/Window.h"
#include "Platform/PlatformInterface.h"

void REditorEditableTextView::BindViewModel(TSharedObjectPtr<REditorWidgetViewModel> InViewModel)
{
    Super::BindViewModel(InViewModel);
    ViewModel=InViewModel;

}

void REditorEditableTextView::CreateWidget(TSharedObjectPtr<RWidget> InWidget)
{
    RWidgetWeakPtr WeakWidget=InWidget;
    auto EditableText=NewWidget<RTextWidget>(InWidget);
    EditableText->Anchor.Fill(InWidget);
    EditableText->Text=[this](){
        return ViewModel->GetDisplayText();
    };
    EditableText->Font=[this](){
        return ViewModel->GetFont();
    };
    EditableText->FontSize=[this](){
        return ViewModel->GetFontSize();
    };
    RTextWidgetWeakPtr WeakEditableText=EditableText;

    auto Beam=NewWidget<RRectangleWidget>(EditableText);
    Beam->Anchor.VerticalFill(EditableText);   
    Beam->Width=2;
    Beam->FillColor=ViewModel->BeamColor;
    Beam->Visible=[this](){
        return ViewModel->IsEditing();
    };
    Beam->X=[this](){
        return ViewModel->GetBeamX();
    };


    auto KeyboardInput=NewWidget<RKeyboardWidget>(EditableText);
    KeyboardInput->Anchor.Fill(EditableText);

    KeyboardInput->Visible=[this,WeakEditableText](){
        //show IME window here,at here, Text widget position is determined
        //TODO find a better way to show IME window
        if(ViewModel->IsEditing() 
        && !ViewModel->bIsIMEWindowOpen 
        )
        {
            ViewModel->bIsIMEWindowOpen=true;
            IPlatformInterface::GetPlatformInterface()->StartTextInput(
                WeakEditableText->GetWindow()->GetWindowID()
                ,WeakEditableText->GetWindow()->ContentSpaceToWindowSpace(
                    SIntPoint(
                        WeakEditableText->PresentAbsPosition.X
                        ,WeakEditableText->PresentAbsPosition.Y+WeakEditableText->PresentSize.Y
                    )
                )
            );
        }

        return true;
    };

    RKeyboardWidgetWeakPtr WeakKeyboardInput=KeyboardInput;
    KeyboardInput->OnKeyboardFocused.Bind([this](){
        if(ViewModel->IsEditing())
        {
            return;
        }
        ViewModel->StartEditing();
    });
    KeyboardInput->OnKeyboardUnfocused.Bind([this](){
        if(!ViewModel->IsEditing())
        {
            return;
        }
        ViewModel->EndEditing(REditorEditableTextViewModel::EReasonForEndEditing::LostFocus);
    });
    KeyboardInput->OnTextInput.Bind([this](const STextInputEvent& InTextEvent){
        return ViewModel->OnTextInput(InTextEvent);
    });
    KeyboardInput->OnKeyboardInput.Bind([this](const SKeyboardEvent& InKeyboardEvent){
        return ViewModel->OnKeyboardEvent(InKeyboardEvent);
    });

    ViewModel->OnEditingStarted.Add([this,WeakKeyboardInput,WeakWidget](){
        if(!WeakKeyboardInput->IsFocused())
        {
            WeakKeyboardInput->Focus();
        }
      
        return ;
    });
    ViewModel->OnEditingEnded.Add([this,WeakKeyboardInput](REditorEditableTextViewModel::EReasonForEndEditing InReasonForEndEditing){
        if(WeakKeyboardInput->IsFocused())
        {
            WeakKeyboardInput->Unfocus();
        }

        if(ViewModel->bIsIMEWindowOpen)
        {
            ViewModel->bIsIMEWindowOpen=false;
            IPlatformInterface::GetPlatformInterface()->StopTextInput();
        }
    });

    auto Mouse=NewWidget<RMouseWidget>(InWidget);
    Mouse->Anchor.Fill(InWidget);
    Mouse->CursorShape=EMouseCursorType::IBeam;
    Mouse->OnClicked.BindLambda([this,WeakEditableText](const SMouseButtonEvent& Event)
    {
        ViewModel->OnMuseButtonClicked(WeakEditableText->GetMousePositionInWidget().X);
        return true;
    });
}